package com.qf.service.impl;

import com.qf.pojo.Order;
import com.qf.service.OrderService;
import com.qf.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@Primary
public class UserServiceImpl implements UserService {

    /*
        注入远程的OrderService对象
        使用dubbo中的Reference注解，订阅注册中心上的远程服务信息，并且内部会生成代理对象，发起远程访问

        ① 从注册中心拉取这个接口的相关提供端信息-能知道提供端的协议、ip、端口，包括这个接口的调用等信息。并且在消费端缓存起来

        ② 基于动态代理对这个接口进行代理，生成一个代理对象。将这个代理对象注入到Spring容器中。这个代理对象的invoke方法中的代码
            是在向提供方的web容器基于协议、ip、端口和接口的访问信息发起远程访问，并接收提供端的结果。


        注意：一旦远程调用超时后，dubbo默认会帮我们重试2次，所以一旦出现超时异常， 会发现提供方的业务被调用了3次。而且即使出现了超时异常
            提供方的业务不会终止。此时重试可能导致一个幂等性的问题。

            幂等性：多次执行的结果一致，称之为幂等。多次执行的结果不一样，称之为非幂等。

            新增：非幂等

            删除：幂等

            修改：
                update 表名 set 列1=值1,列2=值2,... where id=1    -- 幂等
                update 表名 set 列1=列1+值1,列2=列2+值2,.... where id=1  -- 非幂等

                设置型语句 -- 幂等
                计算型语句 -- 非幂等

            查询：幂等


        负载均衡:
            random: 随机
            ***roundrobin: 权重轮询
                提供端配置权重： provider1-权重是50，provider2-权重100. provider1访问1次，provider2访问2次
            leastactive：最小活跃优先。能者多劳。处理能力越强，同时在处理的请求数量就会越少。
            shortestresponse: 最少响应时间，响应时间越快，越倾向于将请求给你
            consistenthash: 一致性hash，在消费端向提供端发起请求时，需要带一个参数，参数值不变，最终永远都访问的是同一台目标提供者

        集群容错: 当访问集群中某台机器，出现异常后，对待这次访问异常的策略
            ***failover: 一旦出错了，会重试，重试其他集群中的机器 （适合于幂等操作）
            ***failfast: 一旦出错，不再重试 （是合于非幂等操作）

            failsafe: 失败了，悄摸得将信息记录下来，不告诉调用者
            failback: 失败了，一直重试，在调用失败的那台机器上重试
            forking: 一次访问集群中所有机器，只要有一台成功即可
            broadcast: 一次访问集群中所有机器，只要有一台报错，就失败


     */
    @Reference(timeout = 3000/*,retries = 0*/,version = "2.0",loadbalance = "roundrobin",
            cluster = "failfast",
            stub = "com.qf.stubs.OrderServiceStub",
            mock = "com.qf.mocks.OrderServiceMock"
    )
    private OrderService orderService;

    @Override
    public List<Order> findById(Integer uid) throws InterruptedException {
        System.out.println("通过远程调用查询用户订单");
        return orderService.findByUid(uid);
    }
}
